package com.kamistoat.meimeimall.meimeimallorder.service;

import com.kamistoat.meimeimall.common.To.RabbitMQTo.OrderTo;
import com.kamistoat.meimeimall.common.To.RabbitMQTo.SecKillOrderTo;
import com.kamistoat.meimeimall.common.To.paymentTo.PayTo;
import com.kamistoat.meimeimall.common.utils.R;
import com.kamistoat.meimeimall.meimeimallorder.vo.OrderCreateVo;
import com.kamistoat.meimeimall.meimeimallorder.entity.OrderEntity;
import com.kamistoat.meimeimall.meimeimallorder.vo.*;

import java.util.List;

/**
 * 订单
 *
 * @author kamistoat
 * @email linjianshanke@163.com
 * @date 2021-09-12 16:42:29
 */
public interface OrderService {

    /**
     * 当用户点击购物车结算时，查出订单检查页面所需要的所有数据
     *
     * @return
     */
    OrderCheckVo checkOrder();

    /**
     * 秒杀商品直接点击 立刻购买时，构建订单检查页。
     * 不会操作信号量锁，只会尽力从缓存中查询数据构建订单检查页。
     *
     * @param sessionId  全局唯一的秒杀场次Id
     * @param randomCode 随机码
     * @param skuId
     * @param num
     */
    OrderCheckVo checkSeckillOrder(Long sessionId, String randomCode, Long skuId, Integer num);

    /**
     * 在订单检查页点击去支付，执行下单动作。
     * 该方法只负责做订单的预处理，预处理通过后就提交下单消息给消息队列.
     *
     * @param orderSubmitVo
     */
    void submitOrder(OrderSubmitVo orderSubmitVo);

    /**
     * 秒杀订单提交订单。
     *
     * @return 等待支付页。但是注意，秒杀高并发下，只能保证缓存中一定存在订单，数据库中订单是否入库未知
     */
    R submitSeckillOrder(OrderSubmitVo orderSubmitVo);

    /**
     * 最新实现。
     * 无论是普通商品，还是促销商品，已经全部统一逻辑。
     */
    void submitOrderForAllType(OrderSubmitVo orderSubmitVo);

    /**
     * 关闭订单
     */
    void closeOrder(OrderTo orderTo);

    /**
     * 根据orderSN制作支付vo
     *
     * @param orderSn
     * @return
     */
    PayTo getOrderPayVo(Long memberId, String orderSn);

    /**
     * 带缓查询当前用户的所有订单(包括总订单和拆分后的小订单)
     *
     * @param memberId 用户Id
     * @return
     */
    List<OrderListVo> getOrderListAll(Long memberId);

    /**
     * 带缓查询当前用户的分页总订单
     *
     * @param memberId 用户Id
     * @return
     */
    List<OrderListVo> getOrderListPage(Long memberId, Integer page, Integer pageSize);

    /**
     * 查询当前用户指定订单
     */
    OrderListVo getOrderBySN(Long memberId, String orderSn);

    /**
     * 查询指定未支付订单的详情。设计核心业务，强制从数据库查询
     *
     * @param orderSN 订单SN
     */
    OrderEntity getUnpayOrder(Long memberId, String orderSN);

    /**
     * 带缓查询指定任意订单的详情。优先从缓存中的用户订单列表中查询
     *
     * @param orderSN 订单SN
     */
    OrderListVo getAnyOrder(Long memberId, String orderSN);

    /**
     * 创建秒杀订单
     *
     * @param secKillOrderTo 消息队列中的秒杀信息
     */
    void secKillOrder(SecKillOrderTo secKillOrderTo);

    /**
     * 新秒杀逻辑下，监听到消息队列中的 未支付状态的新秒杀订单，将其入库
     *
     * @param orderCreateVo 未支付状态的秒杀订单
     */
    void saveSeckillNewOrder(OrderCreateVo orderCreateVo);

    /**
     * 根据订单检查页面传递来的有限参数，最后一次去数据库查询并构建订单.
     * 在这一步中会做 订单小项 真实价格的计算，即把优惠价格加权平均到订单小项上.
     * 本方法中不涉及数据库修改，全部都是数据库查询.
     * P.S. 注意普通商品订单和秒杀商品订单的处理逻辑会有些许不同
     *
     * @return OrderCreateVo
     */
    OrderCreateVo createOrderBySubmit(OrderSubmitVo orderSubmitVo);

    void confirmOrder(Long memberId, String orderSN);

    /**
     * 解析并保存新创建的订单
     */
    void saveCreateOrder(OrderCreateVo orderCreateVo);

    void saveCreateDoneOrder(OrderCreateVo orderCreateVo);
}

